package director;

import behavior.interpreter.AbstractExpression;
import behavior.interpreter.NonTerminalExpression;
import behavior.interpreter.ParseContext;
import behavior.interpreter.TerminalExpression;

import java.math.BigDecimal;
import java.util.Stack;
import java.util.StringTokenizer;

public class InterpreterDirector {

    public static void main(String[] args){
        String expression = "a + b * 4 * 3 + d * 2";

        try {
            AbstractExpression finalExpression = parseExpression(expression);
            ParseContext pc = new ParseContext();
            pc.addValue("a", BigDecimal.ONE);
            pc.addValue("b", new BigDecimal("2"));
            pc.addValue("d", new BigDecimal("3"));
            System.out.println(finalExpression.interpreter(pc));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static AbstractExpression parseExpression(String expression) throws Exception {
        //解析的主要思路是表达式的优先级分类，将加减乘除分成两个优先级分别处理
        //第一遍遍历解析 * / 表达式，消除一级表达式形成NonTerminalExpression，最终将所有表达式压栈
        //第二遍遍历结合 + - 表达式和第一遍遍历形成的表达式堆栈组合成finalExpression
        Stack<AbstractExpression> expressionStack = new Stack<>();
        Stack<String> opStatck = new Stack<>();
        StringTokenizer st = new StringTokenizer(expression," ");
        while(st.hasMoreTokens()){
            String nextEle = st.nextToken();
            if("*".equals(nextEle) || "/".equals(nextEle)){
                AbstractExpression pre = expressionStack.pop();
                AbstractExpression post = new TerminalExpression(st.nextToken());
                expressionStack.push(new NonTerminalExpression(pre,post, nextEle));
            }else if("+".equals(nextEle) || "-".equals(nextEle)){
                opStatck.push(nextEle);
            }else{
                AbstractExpression thisExpression = new TerminalExpression(nextEle);
                expressionStack.push(thisExpression);
            }
        }
        while(!opStatck.empty()){
            AbstractExpression pre = expressionStack.pop();
            AbstractExpression post = expressionStack.pop();
            String symbol = opStatck.pop();
            expressionStack.push(new NonTerminalExpression(pre,post, symbol));
        }
        if(expressionStack.size() != 1) throw new Exception("fatal");
        return expressionStack.pop();
    }
}
